"""
质量评分数据模型
"""
from enum import Enum
from typing import Dict, Optional, List, Any
from datetime import datetime, timezone
from pydantic import BaseModel, Field, field_validator, ConfigDict
from bson import ObjectId


class QualityDimension(Enum):
    """质量维度枚举"""
    ORIGINALITY = "originality"  # 原创性
    READABILITY = "readability"  # 可读性
    INFORMATION_DENSITY = "information_density"  # 信息量
    EMOTIONAL_RESONANCE = "emotional_resonance"  # 情感共鸣
    STRUCTURE_INTEGRITY = "structure_integrity"  # 结构完整性


class ScenarioType(Enum):
    """场景类型枚举"""
    NEWS = "news"  # 新闻
    BLOG = "blog"  # 博客
    TECHNICAL = "technical"  # 技术文档
    CREATIVE = "creative"  # 创意写作
    GENERAL = "general"  # 通用


class DimensionScore(BaseModel):
    """单个维度的评分"""
    dimension: QualityDimension
    score: float = Field(ge=0, le=100, description="维度分数(0-100)")
    weight: float = Field(ge=0, le=1, description="权重(0-1)")
    explanation: str = Field(default="", description="评分说明")
    deductions: List[str] = Field(default_factory=list, description="扣分项列表")

    model_config = ConfigDict(use_enum_values=True)


class ScoreResult(BaseModel):
    """评分结果数据结构"""
    total_score: float = Field(ge=0, le=100, description="总分(0-100)")
    dimensions: Dict[str, DimensionScore] = Field(description="各维度评分")
    scenario: ScenarioType = Field(default=ScenarioType.GENERAL, description="场景类型")
    weights: Dict[str, float] = Field(description="使用的权重配置")
    explanation: Dict[str, Any] = Field(default_factory=dict, description="详细解释")
    confidence: float = Field(ge=0, le=1, default=1.0, description="评分置信度")

    model_config = ConfigDict(use_enum_values=True)

    @field_validator('dimensions')
    @classmethod
    def validate_dimensions(cls, v):
        """验证所有维度都有评分"""
        required_dims = set(dim.value for dim in QualityDimension)
        provided_dims = set(v.keys())
        if not required_dims.issubset(provided_dims):
            missing = required_dims - provided_dims
            raise ValueError(f"Missing dimension scores: {missing}")
        return v

    @field_validator('weights')
    @classmethod
    def validate_weights(cls, v):
        """验证权重总和为1"""
        total = sum(v.values())
        if abs(total - 1.0) > 0.01:  # 允许小误差
            raise ValueError(f"Weights must sum to 1.0, got {total}")
        return v


class ScoreHistory(BaseModel):
    """历史评分记录模型"""
    id: Optional[str] = Field(default=None, description="记录ID")
    content_id: str = Field(description="内容ID")
    content_type: str = Field(default="article", description="内容类型")
    content_preview: Optional[str] = Field(default=None, description="内容预览(前200字)")
    scores: ScoreResult = Field(description="评分结果")
    evaluated_at: datetime = Field(default_factory=lambda: datetime.now(timezone.utc), description="评估时间")
    evaluator_version: str = Field(default="1.0.0", description="评分器版本")
    metadata: Dict[str, Any] = Field(default_factory=dict, description="额外元数据")
    
    model_config = ConfigDict(
        json_encoders={
            datetime: lambda v: v.isoformat(),
            ObjectId: lambda v: str(v)
        }
    )
    
    def to_mongo(self) -> dict:
        """转换为MongoDB文档格式"""
        data = self.model_dump(exclude={'id'}, mode='json')
        if self.id:
            data['_id'] = ObjectId(self.id)
        return data
    
    @classmethod
    def from_mongo(cls, data: dict) -> "ScoreHistory":
        """从MongoDB文档创建实例"""
        if '_id' in data:
            data['id'] = str(data.pop('_id'))
        # 重建嵌套的Pydantic模型
        if 'scores' in data and not isinstance(data['scores'], ScoreResult):
            # 重建DimensionScore对象
            dimensions = {}
            for dim_name, dim_data in data['scores'].get('dimensions', {}).items():
                if not isinstance(dim_data, DimensionScore):
                    dimensions[dim_name] = DimensionScore(**dim_data)
                else:
                    dimensions[dim_name] = dim_data
            data['scores']['dimensions'] = dimensions
            data['scores'] = ScoreResult(**data['scores'])
        return cls(**data)


class QualityMetrics(BaseModel):
    """质量统计指标"""
    content_id: Optional[str] = Field(default=None, description="内容ID(可选)")
    average_score: float = Field(description="平均分")
    score_count: int = Field(description="评分次数")
    dimension_averages: Dict[str, float] = Field(description="各维度平均分")
    score_distribution: Dict[str, int] = Field(description="分数分布")
    trend: Optional[str] = Field(default=None, description="趋势(improving/declining/stable)")
    period_start: Optional[datetime] = Field(default=None, description="统计周期开始")
    period_end: Optional[datetime] = Field(default=None, description="统计周期结束")


class BatchScoreRequest(BaseModel):
    """批量评分请求"""
    contents: List[Dict[str, Any]] = Field(description="待评分内容列表")
    scenario: Optional[ScenarioType] = Field(default=None, description="场景类型")
    custom_weights: Optional[Dict[str, float]] = Field(default=None, description="自定义权重")
    
    @field_validator('contents')
    @classmethod
    def validate_contents(cls, v):
        """验证内容列表不为空"""
        if not v:
            raise ValueError("Contents list cannot be empty")
        if len(v) > 100:
            raise ValueError("Maximum 100 contents allowed per batch")
        return v


class ScoreRequest(BaseModel):
    """单个评分请求"""
    content: str = Field(description="待评分内容")
    content_id: Optional[str] = Field(default=None, description="内容ID")
    content_type: str = Field(default="article", description="内容类型")
    scenario: Optional[ScenarioType] = Field(default=None, description="场景类型")
    custom_weights: Optional[Dict[str, float]] = Field(default=None, description="自定义权重")
    
    @field_validator('content')
    @classmethod
    def validate_content(cls, v):
        """验证内容不为空"""
        if not v or not v.strip():
            raise ValueError("Content cannot be empty")
        if len(v) > 100000:  # 限制最大10万字符
            raise ValueError("Content too long (max 100000 characters)")
        return v


class ScoreResponse(BaseModel):
    """评分响应"""
    score_result: ScoreResult
    score_id: Optional[str] = Field(default=None, description="评分记录ID")
    timestamp: datetime = Field(default_factory=lambda: datetime.now(timezone.utc))
    message: Optional[str] = Field(default=None, description="额外信息")